using System.Collections.Generic;
using System.IO;
using System.Reflection;
using DZTC.UselessAppEver.Base32;
using DZTC.UselessAppEver.Base32.Exceptions;
using DZTC.UselessAppEver.UI;
using NUnit.Framework;

namespace DZTC.UselessAppEver.Tests
{
    [TestFixture]
    public class Base32Tests
    {
        [Test]
        public void TestGetDestinationLength()
        {
            Assert.AreEqual(8, Encoder.GetDestinationLength(1));
            Assert.AreEqual(8, Encoder.GetDestinationLength(2));
            Assert.AreEqual(16, Encoder.GetDestinationLength(6));
        }

        // http://golang.org/src/pkg/encoding/base32/base32_test.go
        private readonly Dictionary<string, string> pairs = new Dictionary<string, string>()
            {
                {"", ""},
                {"f", "MY======"},
                {"fo", "MZXQ===="},
                {"foo", "MZXW6==="},
                {"foob", "MZXW6YQ="},
                {"fooba", "MZXW6YTB"},
                {"foobar", "MZXW6YTBOI======"},
    	
                // Wikipedia examples, converted to base32
                {"sure.", "ON2XEZJO"},
                {"sure", "ON2XEZI="},
                {"sur", "ON2XE==="},
                {"su", "ON2Q===="},
                {"leasure.", "NRSWC43VOJSS4==="},
                {"easure.", "MVQXG5LSMUXA===="},
                {"asure.", "MFZXK4TFFY======"},
                {"Twas brillig, and the slithy toves", "KR3WC4ZAMJZGS3DMNFTSYIDBNZSCA5DIMUQHG3DJORUHSIDUN53GK4Y="}

            };

        [Test]
        public void EncoderSmokeTest()
        {
            foreach (var pair in pairs)
            {
                Assert.AreEqual(pair.Value, Base32.Base32Converter.EncodeString(pair.Key));
            }
        }

        [Test]
        public void DecoderSmokeTest()
        {

            foreach (var pair in pairs)
            {
                Assert.AreEqual(pair.Key, Base32.Base32Converter.DecodeString(pair.Value));
            }
        }

        [Test]
        public void TestDecoderSkipsAndErrors()
        {
            Assert.AreEqual("foobar", Base32.Base32Converter.DecodeString("==M==Z==XW6YTBOI======"));
            Assert.AreEqual("foobar", Base32.Base32Converter.DecodeString("==M==Z==XW6\r\nYTBOI==\r\n====\r"));

            Assert.Throws<InvalidCharacterException>(
                () => Base32.Base32Converter.DecodeString("=||=M==Z==XW6\r\nYTBOI==\r\n====\r"));
            Assert.Throws<InvalidPaddingException>(() => Base32.Base32Converter.DecodeString("==M==Z==XW6\r\nYTBOI==\r\n===\r"));


        }

        private Stream GetData()
        {
            return Assembly.GetExecutingAssembly()
                .GetManifestResourceStream("DZTC.UselessAppEver.Tests.Base32TestData");
        }

        [Test]
        public void TestEncodeDecodeOnSomeBigData()
        {
            using (var input = GetData())
            using (var output = new MemoryStream())
            using (var output2 =new MemoryStream())
            {
                Base32Converter.Encode(input, output);

                output.Seek(0, SeekOrigin.Begin);
                Base32Converter.Decode(output, output2);

                Assert.AreEqual(input.Length, output2.Length);

                input.Seek(0, SeekOrigin.Begin);

                var buf2 = output2.GetBuffer();
                
                for (int i = 0; i < input.Length; i++)
                {
                    Assert.AreEqual(input.ReadByte(), buf2[i]);
                }
            }
        }
    }
}